// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ************************************************************************* //
//  File: avtIndexSelectFilter.h
// ************************************************************************* //

#ifndef AVT_IndexSelect_FILTER_H
#define AVT_IndexSelect_FILTER_H

#include <avtPluginDataTreeIterator.h>

#include <IndexSelectAttributes.h>

class vtkDataSet;
class vtkMaskPoints;
class vtkVisItExtractGrid;
class vtkVisItExtractRectilinearGrid;
class vtkRectilinearGrid;
class vtkDataArray;


// ****************************************************************************
//  Class: avtIndexSelectFilter
//
//  Purpose:
//      A plugin operator for IndexSelect.
//
//  Programmer: childs -- generated by xml2info
//  Creation:   Wed Jun 5 09:09:10 PDT 2002
//
//  Modifications:
//
//    Hank Childs, Sat Jun 29 16:22:48 PDT 2002
//    Added support for groups.
//
//    Mark C. Miller, Tue Sep 28 19:57:42 PDT 2004
//    Added data selection id
//
//    Kathleen Bonnell, Tue May 10 11:19:24 PDT 2005 
//    Use VisIt versions of vtkExtractGrid and vtkExtractRectilinearGrid, 
//    they have been modified to correctly handle cell data when VOI is
//    along max boundary. 
//
//    Kathleen Bonnell, Thu Aug  4 15:47:59 PDT 2005 
//    Added UpdateDataObjectInfo.
//
//    Kathleen Bonnell,  Mon Jan 30 15:10:26 PST 2006 
//    Add vtkMaskPoints for a points filter. 
//
//    Jeremy Meredith, Wed Jan 17 11:41:51 EST 2007
//    Added support for transformed rectilinear grids.
//
//    Kathleen Bonnell, Thu Jun 21 16:31:59 PDT 2007 
//    Added amrLevel, amrMesh, int* arg to PrepareFilters.
//
//    Eric Brugger, Mon Jul 28 15:33:34 PDT 2014
//    Modified the class to work with avtDataRepresentation.
//
//    Kathleen Biagas, Tue Jun 9 09:37:12 MST 2015
//    Changes to 'Replicate', added helper class for 'wrap' option.
//
//    Alister Maguire, Mon Oct 24 12:25:39 PDT 2016 
//    Removed curvilinearFilter, rectilinearFilter, and pointsFilter
//    for thread safety; they are now stack variables within 
//    ExecuteData. Added vtkVisItExtractGrid, vtkVisItExtractRectilinearGrid,
//    and vtkMaskPoints arguments to PrepareFilters. Changed 
//    successfullyExecuted to atLeastOneThreadSuccessfullyExecuted.
//    Added ThreadSafe method to header file.  
//
// ****************************************************************************

class avtIndexSelectFilter : public avtPluginDataTreeIterator
{
  public:
                         avtIndexSelectFilter();
    virtual             ~avtIndexSelectFilter();

    static avtFilter    *Create();

    virtual const char  *GetType(void)  { return "avtIndexSelectFilter"; };
    virtual const char  *GetDescription(void)
                             { return "Index selecting"; };
    virtual void         ReleaseData(void);

    virtual void         SetAtts(const AttributeGroup*);
    virtual bool         Equivalent(const AttributeGroup*);

  protected:
    IndexSelectAttributes       atts;
    bool                        haveIssuedWarning;
    bool                        atLeastOneThreadSuccessfullyExecuted;
    int                         selID; 
    bool                        groupCategory;
    bool                        amrMesh;
    int                         amrLevel;


    virtual bool                ThreadSafe(void) { return(true); };
    void                        PrepareFilters(int [3], int *, 
                                               vtkVisItExtractGrid *, 
                                               vtkVisItExtractRectilinearGrid *,
                                               vtkMaskPoints *);

    virtual avtDataRepresentation *ExecuteData(avtDataRepresentation *);
    virtual void                PreExecute(void);
    virtual void                PostExecute(void);
    virtual void                UpdateDataObjectInfo(void);
    virtual void                VerifyInput(void);

    virtual avtContract_p       ModifyContract(avtContract_p);
    virtual bool                FilterUnderstandsTransformedRectMesh();

    virtual void        Replicate(void);
    vtkDataSet         *Replicate(int wrap, vtkDataSet *min_ds,
                                            vtkDataSet *max_ds);
    vtkDataSet         *Replicate(vtkRectilinearGrid *rgrid, bool wrap[3],
                                  int dims_in[3], int max[3]);

    virtual vtkDataArray *GetCoordinates( vtkRectilinearGrid *grid,
                                          unsigned int coor);

    virtual void SetCoordinates( vtkRectilinearGrid *grid,
                                 vtkDataArray *coordinates,
                                 unsigned int coor);

  private:
    class LogicalSpaces
    {
        // helper class for 'wrap' option
        public:
            LogicalSpaces();
            LogicalSpaces(int *mins);
           ~LogicalSpaces();
            void SetMins(int *);
            void SetMaxs(int *);

            bool HasMinAt(int idx, int _min);
            bool MatchesMaxAt(int idx, int _max);
            bool MatchesMins(int _min[3]);
            int rank;
            int block;
            int mins[3];
            int maxs[3];
    };
    int globalDims[6];
    std::vector<LogicalSpaces> lspace;
    void CopyData(vtkDataSet *, vtkDataSet *, int dims_in[3], int  dims_out[3]);
};


#endif
